package com.huazhi.wzsnw.util;

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class KitFileUtil {
    private static ServletContext servletContext;
    private final static String FileUpload = "upload";

    public Map<String, Object> kitFileUtil(/*@RequestParam("uploadFiles") */MultipartFile[] uploadFiles,
                                           HttpServletRequest request, String dirName,String moduleName) {
        if (uploadFiles.length==0){
            return getError("未选择文件！");
        }
        if(moduleName != null && !moduleName.equals("")){
            moduleName = moduleName + "/";
        }
        // 文件保存目录路径
        String path = PropertyUtil.getText("buildPath");//文件生成路径
        File toFile = new File(path);
        if (!toFile.exists()) {
            toFile.mkdirs();
        }
        String savePath = path + "/" + FileUpload + "/" + moduleName;
//        String savePath = request.getSession().getServletContext().getRealPath("/") +FileUpload+ "/"  + moduleName;
        System.out.println("正确路径1：" + savePath);
        //文件保存目录URL
        String saveUrl = "http://" + PropertyUtil.getText("showPath")+ "/" + FileUpload + "/" + moduleName;
//        String saveUrl = request.getContextPath() + "/" + FileUpload + "/" + moduleName;
        //定义允许上传的文件扩展名
        HashMap<String, String> extMap = new HashMap<String, String>();
        extMap.put("image", "gif,jpg,jpeg,png,bmp");
        extMap.put("flash", "swf,flv");
        extMap.put("video", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb,mp4");
        extMap.put("file", "doc,docx,xls,xlsx,ppt,txt,zip,rar,gz,bz2,pdf");
        extMap.put("audio","mp3,mid,wma,amr,m4a,aif,wav");
        extMap.put("files","gif,jpg,jpeg,png,bmp,swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf," +
                "rm,rmvb,mp4,doc,docx,xls,xlsx,ppt,txt,zip,rar,gz,bz2,,amr,m4a,aif,pdf");
        //最大文件大小
        long maxSize = 10485760000L;
        //response.setContentType("text/html; charset=UTF-8");
        //判断客户端<form>标记的enctype属性是否是“multipart/form-data"
        if (!ServletFileUpload.isMultipartContent(request)) {
            return getError("请选择文件。");
        }
        //检查目录
        File uploadDir = new File(savePath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
            //return getError("上传目录不存在。");
        }
        //检查目录写权限
        if (!uploadDir.canWrite()) {
            return getError(dirName+"上传目录没有写权限。");
        }
        /*//获取请求中dir的参数
        String dirName = request.getParameter("dir");
        if (dirName == null) {
            dirName = "image";
        }*/
        //校验文件格式（map）中是否存在该键
        if (!extMap.containsKey(dirName)) {
            return getError(dirName+"目录名不正确。");
        }
        //生成文件目录
        savePath += dirName + "/";
        saveUrl += dirName + "/";
        //判断目录是否存在，不存在则创建文件夹
        File saveDirFile = new File(savePath);
        if (!saveDirFile.exists()) {
            saveDirFile.mkdirs();
        }
        //创建年月日目录，
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String ymd = sdf.format(System.currentTimeMillis());
        savePath += ymd + "/";
        saveUrl += ymd + "/";
        //判断当天目录是否存在，不存在则创建文件夹
        File dirFile = new File(savePath);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        String[] url = new String[uploadFiles.length];
        //String rName [] = new String[uploadFiles.length];
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < uploadFiles.length; i++) {
            System.out.println(uploadFiles[i]);
            // 获取上传文件的名字
            String fileName = uploadFiles[i].getOriginalFilename();
            // 获取长度
            long fileSize = uploadFiles[i].getSize();
            // 如果当前上传的文件不为空
            if (!uploadFiles[i].isEmpty()) {
                // 检查文件大小
                if (uploadFiles[i].getSize() > maxSize) {
                    return getError(dirName+"上传文件大小超过限制。");
                }
                // 截取扩展名 toLowerCase用于将大写字符转换为小写  +1表示不包括.开始截取
                String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
                //文件原有名称,替换掉,
                String name = fileName.substring(0,fileName.lastIndexOf(".")).replace(",","");
                // 校验该扩展名是否在该键对应的格式中 contains:当且仅当此字符串包含指定的char值序列时，返回true
                if (!Arrays.<String>asList(extMap.get(dirName).split(",")).contains(fileExt)) {
                    return getError(dirName+"上传文件扩展名是不允许的扩展名。\n只允许" + extMap.get(dirName) + "格式。");
                }
                SimpleDateFormat df = new SimpleDateFormat("HHmmss");
                //文件重命名：时分秒+随机数+.+后缀格式   Random().nextInt(1000)生成一个0~999的随机整数
                int number = new Random().nextInt(1000);
                String num = number < 100 ? "0" + number : "" + number;
                num = number < 10 ? "0" + num : num;
                String newFileName = df.format(System.currentTimeMillis()) + num + name + "." + fileExt;
                try {
                    // 保存文件
                    System.out.println(saveUrl + newFileName);
                    // 复制 source 文件到 target
                    FileCopyUtils.copy(uploadFiles[i].getInputStream(), new FileOutputStream(savePath + newFileName));
                } catch (Exception e) {
                    return getError(dirName+"上传文件失败。");
                }

                url[i] = saveUrl + newFileName;
                //rName[i] = dirName + "/" + ymd + "/" + newFileName;
                //                map.put("error", 0);
                //                map.put("url", saveUrl + newFileName);
                //                return map;
            }
        }
        map.put("error", "0");
        map.put("url", url);
        //map.put("newFileName",rName);
        return map;
        // return getError("服务器端错误。");
    }

    public void downloadFile(List<String> pathlist, String titleName, HttpServletRequest request, HttpServletResponse response){
        try {
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            //设置压缩包的名字
            //解决不同浏览器压缩包名字含有中文时乱码的问题
            String downloadName = titleName + ".zip";
            //String downloadName = "MemberQR"+".zip";
            //返回客户端浏览器的版本号、类型
            String agent = request.getHeader("USER-AGENT");
            //针对IE或者以IE为内核的浏览器：
            if (agent.contains("MSIE")||agent.contains("Trident")) {
                downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
            } else {
                //非IE浏览器的处理：
                downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            }
            response.setHeader("Content-Disposition", "attachment;fileName=" + downloadName);
            //设置压缩流：直接写入response，实现边压缩边下载
            ZipOutputStream zipos = null;
            zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            zipos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法
            DataOutputStream os = null;
            if(!pathlist.isEmpty()){
                for(String path:pathlist){
                    String filename = null;
                    path = request.getServletContext().getRealPath(path.replace(request.getContextPath(),""));
                    if(pathlist.size() == 1){
                        filename = titleName + path.substring(path.lastIndexOf("."));
                    }else {
                        //倒数第二个\
                        filename = path.substring(path.lastIndexOf("\\", path.lastIndexOf("\\") - 1) + 1);
                    }
                    File file = new File(path);
                    if(file.exists()){
                        //添加ZipEntry，并ZipEntry中写入文件流
                        //这里，加上i是防止要下载的文件有重名的导致下载失败
                        zipos.putNextEntry(new ZipEntry(filename));
                        os = new DataOutputStream(zipos);
                        InputStream is = new FileInputStream(file);
                        byte[] b = new byte[100];
                        int length = 0;
                        while((length = is.read(b))!= -1){
                            os.write(b, 0, length);
                        }
                        is.close();
                        zipos.closeEntry();
                    }
                }
                //关闭流
                os.flush();
                os.close();
            }
            zipos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Map<String, Object> uploadFiles(MultipartFile[] files, String dirName, String moduleName, HttpServletRequest request){
        Map<String,Object> map = new HashMap<>();
        StringBuilder path = new StringBuilder();
        if(files.length > 0 && !files[0].isEmpty()){
            map = kitFileUtil(files, request, dirName,moduleName);
            String error = map.get("error").toString();
            if(!"101".equals(error)){
                String[] url = (String[])map.get("url");
                for(String filepath:url){
                    path.append(filepath).append(",");
                }
                path = new StringBuilder(path.substring(0, path.length() - 1));
                map.put("errno",1);
            }else {
                map.put("errno",0);
            }
        }
        map.put("path", path.toString());
        return map;
    }

    public boolean isFileExist(String url, String type, HttpServletRequest request){
        String path = null;
        //定义允许上传的文件扩展名
        HashMap<String, String> extMap = new HashMap<String, String>();
        extMap.put("image", "gif,jpg,jpeg,png,bmp");
        extMap.put("flash", "swf,flv");
        extMap.put("video", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb,mp4");
        extMap.put("file", "doc,docx,xls,xlsx,ppt,txt,zip,rar,gz,bz2,pdf");
        extMap.put("audio","mp3,mid,wma,amr,m4a,aif,wav");
        extMap.put("files","gif,jpg,jpeg,png,bmp,swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf," +
                "rm,rmvb,mp4,doc,docx,xls,xlsx,ppt,txt,zip,rar,gz,bz2,,amr,m4a,aif,pdf");
        if(request != null){
            path = request.getServletContext().getRealPath(url.replace(request.getContextPath() + "/",""));
        }else {
            path = url;
        }
        File testexist = new File(path);
        if (type != null) {
            if(Arrays.<String>asList(extMap.get(type).split(",")).contains(path.substring(path.lastIndexOf(".")+1))){
                return testexist.exists();
            }else {
                return false;
            }
        }else {
            return testexist.exists();
        }
    }

    public String getFileofStrings(String files,String type,HttpServletRequest request){
        if(files != null && !files.equals("")){
            String[] file = files.split(",");
            if(file.length > 0){
                for(String filepath:file){
                    if(isFileExist(filepath,type,request)){
                        return filepath;
                    }
                }
            }
        }
        return null;
    }

    private Map<String, Object> getError(String message) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("error", 101);
        map.put("message", message);
        return map;
    }

    /**
     * 删除文件，可以是文件或文件夹
     *
     * @param fileName
     *            要删除的文件名
     * @return 删除成功返回true，否则返回false
     */
    public boolean delete(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            System.out.println("删除文件失败:" + fileName + "不存在！");
            return false;
        } else {
            if (file.isFile())
                return deleteFile(fileName);
            else
                return deleteDirectory(fileName);
        }
    }

    /**
     * 删除拼接路径文件，可以是文件或文件夹
     *
     * @param fileName
     *            要删除的文件名
     */
    public void deletefiles(String fileName,HttpServletRequest request) {
        if(fileName != null && !fileName.equals("")){
            String [] Path = fileName.split(",");
            for(String path:Path){
                if(request != null){
                    path = request.getServletContext().getRealPath(path.replace(request.getContextPath() + "/",""));
                }
                File file = new File(path);
                if (!file.exists()) {
                    System.out.println("删除文件失败:" + fileName + "不存在！");
                } else {
                    if (file.isFile())
                        deleteFile(fileName);
                    else
                        deleteDirectory(fileName);
                }
            }
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName
     *            要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    private boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功！");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败！");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败：" + fileName + "不存在！");
            return false;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param dir
     *            要删除的目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    private boolean deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            System.out.println("删除目录失败：" + dir + "不存在！");
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        if(files != null){
            for(File file:files){
                // 删除子文件
                if (file.isFile()) {
                    flag = deleteFile(file.getAbsolutePath());
                    if (!flag)
                        break;
                }
                // 删除子目录
                else if (file.isDirectory()) {
                    flag = deleteDirectory(file.getAbsolutePath());
                    if (!flag)
                        break;
                }
            }
        }
        if (!flag) {
            System.out.println("删除目录失败！");
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            System.out.println("删除目录" + dir + "成功！");
            return true;
        } else {
            return false;
        }
    }
}
